package com.huawei.fastble.slice;

import static ohos.bluetooth.BluetoothHost.STATE_OFF;
import static ohos.bluetooth.BluetoothHost.STATE_TURNING_OFF;
/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.clj.fastble.utils.BleLog;
import com.huawei.fastble.FastBleMyApplication;
import com.huawei.fastble.ResourceTable;
import com.huawei.fastble.adapter.BleItemProvider;
import com.huawei.fastble.adapter.BluetoothItemProvider;
import com.huawei.fastble.bean.BluetoothDevice;
import com.huawei.fastble.comm.ObserverManager;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.*;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;
import ohos.bluetooth.BluetoothRemoteDevice;
import ohos.bluetooth.ble.BlePeripheralDevice;
import ohos.bundle.IBundleManager;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.global.resource.NotExistException;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.security.SystemPermission;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
 * 包含普通蓝牙和ble
 */
public class MainAbilitySlice extends AbilitySlice implements AbsButton.CheckedStateChangedListener {
    private static final int REQUEST_CODE_OPEN_GPS = 1;
    private static final int REQUEST_CODE_PERMISSION_LOCATION = 2;

    Switch aSwitch;
    Switch blueSelectSwitch;
    Button startDiscovery;
    Button btnStopDiscovery;
    ProgressBar progressBar;
    ListContainer simpleBlueToothList;
    ListContainer bleList;
    BluetoothItemProvider simpleBlueToothProvider;
    BleItemProvider bleItemProvider;
    List<BluetoothDevice> simpleBlueToothDevices;
    List<BleDevice> bleDevices;
    Text txtBlueState;
    Text txtblueSelect;

    boolean isSelectBlueTooth = true;
    boolean isOpenBlueTooth = false;

    private EventHandler mHandler = new EventHandler(EventRunner.getMainEventRunner());
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        bleDevices = new LinkedList<>();
        simpleBlueToothDevices = new LinkedList<>();

        BleManager.getInstance().init(this);
        BleManager.getInstance()
                .enableLog(true)
                .setReConnectCount(1, 5000)
                .setConnectOverTime(20000)
                .setOperateTimeout(5000);

        aSwitch = (Switch) findComponentById(ResourceTable.Id_bt_switch);
        aSwitch.setCheckedStateChangedListener(this);
        blueSelectSwitch = (Switch) findComponentById(ResourceTable.Id_blue_select_switch);
        blueSelectSwitch.setCheckedStateChangedListener(this);
        txtBlueState = (Text) findComponentById(ResourceTable.Id_blue_state);
        txtblueSelect = (Text) findComponentById(ResourceTable.Id_blue_select_text);

        startDiscovery = (Button) findComponentById(ResourceTable.Id_btn_start_discovery);
        btnStopDiscovery = (Button) findComponentById(ResourceTable.Id_btn_stop_discovery);
        progressBar = (ProgressBar) findComponentById(ResourceTable.Id_progressbar);
        progressBar.setIndeterminate(true);
        progressBar.setProgressWidth(5);

        simpleBlueToothList = (ListContainer) findComponentById(ResourceTable.Id_bluetooth_devices);


        bleList = (ListContainer) findComponentById(ResourceTable.Id_ble_devices);
        initViewData();
    }

    private void initViewData() {
        simpleBlueToothProvider = new BluetoothItemProvider(this, simpleBlueToothDevices);
        simpleBlueToothList.setItemProvider(simpleBlueToothProvider);
        simpleBlueToothProvider.setListener(
                new BluetoothItemProvider.PairOnclickListener() {
                    @Override
                    public void click(BluetoothDevice bluetoothDevice) {
                        boolean isPair = bluetoothDevice.getBlueRemoteDevice().startPair();
                    }
                });
        bleItemProvider = new BleItemProvider(this, bleDevices);
        bleList.setItemProvider(bleItemProvider);
        bleItemProvider.setListener(
                new BleItemProvider.ConnectOnclickListener() {
                    @Override
                    public void click(BleDevice bleDevice) {
                        connect(bleDevice);
                    }
                });

        bleItemProvider.setHandleOnclickListener(
                new BleItemProvider.HandleOnclickListener() {
                    @Override
                    public void click(BleDevice bleDevice) {
                        intentToNext(bleDevice);
                        // 不想传参，方便读取的手段
                        FastBleMyApplication.setBleDevice(bleDevice);
                    }
                });
        bleList.setClickedListener(component -> {
            BleManager.getInstance().cancelScan();
            showProgressBar(false);
        });
        startDiscovery.setClickedListener(
                new Component.ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        if (isOpenBlueTooth) {
                            if (isSelectBlueTooth) {
                                BleManager.getInstance().scan(scanCallback);
                                showProgressBar(true);

                                if (bleDevices.size() > 0) {
                                    bleDevices.clear();
                                    bleItemProvider.notifyDataChanged();
                                }

                            } else {
                                BleManager.getInstance().bluetToothScan(blueToothScanCallback);
                                showProgressBar(true);
                                if (simpleBlueToothDevices.size() > 0) {
                                    simpleBlueToothDevices.clear();
                                    simpleBlueToothProvider.notifyDataChanged();
                                }
                            }
                        } else {
                            toast("你还没打开蓝牙");
                        }
                    }
                });

        btnStopDiscovery.setClickedListener(
                new Component.ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        if (isSelectBlueTooth) {
                            showProgressBar(false);
                            bleItemProvider.notifyDataChanged();
                            BleManager.getInstance().cancelScan();
                        } else {
                            BleManager.getInstance().cancelBlueToothScan();
                            showProgressBar(false);
                        }
                    }
                });

        if (!isPermission(getAbility(), SystemPermission.LOCATION)) {
            getAbility()
                    .requestPermissionsFromUser(
                            new String[] {SystemPermission.LOCATION}, REQUEST_CODE_PERMISSION_LOCATION);
        }

        if (BleManager.getInstance().getBluetoothManager().getBtState() == STATE_OFF
                || BleManager.getInstance().getBluetoothManager().getBtState() == STATE_TURNING_OFF) {
            aSwitch.setChecked(false);
        } else {
            aSwitch.setChecked(true);
        }

        blueSelectSwitch.setChecked(true);
    }

    private void intentToNext(BleDevice device) {
        FastBleMyApplication.setBleDevice(device);
        Intent intent = new Intent();
        Operation operationBuilder =
                new Intent.OperationBuilder()
                        .withAbilityName("com.huawei.fastble.ServiceListAbility")
                        .withDeviceId("")
                        .withBundleName(getBundleName())
                        .build();

        intent.setOperation(operationBuilder);
        startAbility(intent);
    }

    @Override
    public void onCheckedChanged(AbsButton absButton, boolean b) {
        if (absButton.getId() == ResourceTable.Id_bt_switch) { // 蓝牙开关
            isOpenBlueTooth = b;
            if (b) {
                BleManager.getInstance().openBluetooth();
                txtBlueState.setText("ON");
                txtBlueState.setTextColor(Color.RED);
            } else {
                BleManager.getInstance().closeBluetooth();
                txtBlueState.setText("OFF");
                txtBlueState.setTextColor(Color.GRAY);
            }
        } else if (absButton.getId() == ResourceTable.Id_blue_select_switch) { // 选择普通蓝牙还是ble蓝牙 ，默认是ble蓝牙
            isSelectBlueTooth = b;
            if (b) {
                txtblueSelect.setText("BLE操作");
                startDiscovery.setText("BLE扫描");
//                Element scatter = ElementScatter.getInstance(this).parse(ResourceTable.Graphic_btn_red_element);
//                startDiscovery.setBackground(scatter);

                simpleBlueToothList.setVisibility(Component.HIDE);
                bleList.setVisibility(Component.VISIBLE);
            } else {
                txtblueSelect.setText("普通蓝牙操作");
                Color color = new Color(getColor(this, ResourceTable.Color_accent));
                txtblueSelect.setTextColor(color);
                startDiscovery.setText("普通蓝牙扫描");
//                Element scatter = ElementScatter.getInstance(this).parse(ResourceTable.Graphic_btn_blue_element);
//                startDiscovery.setBackground(scatter);

                simpleBlueToothList.setVisibility(Component.VISIBLE);
                bleList.setVisibility(Component.HIDE);
            }
        }
    }

    private static int getColor(Context context, int id) {
        int result = 0;
        if (context == null) {
            return result;
        }
        ResourceManager manager = context.getResourceManager();
        if (manager == null) {
            return result;
        }
        try {
            result = manager.getElement(id).getColor();
        } catch (IOException e) {
            BleLog.error(e.toString());
        } catch (NotExistException e) {
            BleLog.error(e.toString());
        } catch (WrongTypeException e) {
            BleLog.error(e.toString());
        }
        return result;
    }

    /**
     * 判断权限是否已经获取
     *
     * @param context context
     * @param permission permission
     * @return boolean
     */
    private boolean isPermission(Context context, String permission) {
        if (context.verifyCallingPermission(permission) == IBundleManager.PERMISSION_GRANTED) {
            return true;
        }
        return false;
    }

    /**
     * ble 蓝牙扫描回调，ble
     * openHarmony里面返回的数据中中，没有name，没有mac也没有address，只有厂商数据标识，
     * 所以无法只能显示厂商数据了
     */
    private BleScanCallback scanCallback =
            new BleScanCallback() {
                @Override
                public void onScanFinished() {

                    showProgressBar(false);

                    toast("扫描完成");
                }

                @Override
                public void onScanStarted(boolean success) {
                    showProgressBar(success);
                }

                @Override
                public void onScanning(BleDevice bleDevice) {
                    bleItemProvider.addDevice(bleDevice);

                    mHandler.postTask(new Runnable() {
                        @Override
                        public void run() {
                            bleItemProvider.notifyDataChanged();
                        }
                    });
                }
            };

    /**
     * blutTooth 普通蓝牙扫描 ，，因为ble在hmos太多坑，所以还写了普通蓝牙扫描
     */
    private BlueToothScanCallback blueToothScanCallback =
            new BlueToothScanCallback() {
                @Override
                public void notifyDiscoveryState(boolean isStarted) {
                    // 扫描状态改变
                    if (isStarted) {
                        progressBar.setVisibility(Component.VISIBLE);
                    } else {
                        progressBar.setVisibility(Component.HIDE);
                    }
                }

                @Override
                public void notifyBluetoothStatusChanged() {
                    // 蓝牙状态改变
                    if (BleManager.getInstance().getBluetoothManager().getBtState() == STATE_OFF
                            || BleManager.getInstance().getBluetoothManager().getBtState() == STATE_TURNING_OFF) {
                        aSwitch.setChecked(false);
                    } else {
                        aSwitch.setChecked(true);
                    }
                }

                @Override
                public void updateAvailableDevices(BluetoothRemoteDevice btRemoteDevice) {
                    // 扫描到的有效蓝牙
                    //              toast(btRemoteDevice.getDeviceAddr()+"");
                    BluetoothDevice device = new BluetoothDevice();
                    device.setAddress(btRemoteDevice.getDeviceAddr());
                    device.setBlueRemoteDevice(btRemoteDevice);

                    Optional<String> optName = btRemoteDevice.getDeviceName();
                    String name = optName.orElse(btRemoteDevice.getDeviceAddr());
                    device.setName(name);

                    simpleBlueToothDevices.add(device);

                    simpleBlueToothProvider.notifyDataChanged();
                }

                @Override
                public void updatePairedDevices(BluetoothRemoteDevice btRemoteDevice) {
                    // 扫描到已配对的蓝牙

                }

                @Override
                public void updateFinishScanResult(List<BluetoothRemoteDevice> blueToothDevices) {
                    // 扫描完成后扫描结果
                    for (BluetoothRemoteDevice btRemoteDevice : blueToothDevices) {
                        BluetoothDevice device = new BluetoothDevice();
                        device.setAddress(btRemoteDevice.getDeviceAddr());
                        device.setBlueRemoteDevice(btRemoteDevice);

                        Optional<String> optName = btRemoteDevice.getDeviceName();
                        String name = optName.orElse(btRemoteDevice.getDeviceAddr());

                        device.setName(name);
                        simpleBlueToothDevices.add(device);
                    }
                    simpleBlueToothProvider.notifyDataChanged();

                    showProgressBar(false);
                }
            };

    /**
     * ble
     *
     * @param bleD bleD
     */
    private void connect(final BleDevice bleD) {
        BleManager.getInstance()
                .connect(
                        bleD,
                        new BleGattCallback() {
                            @Override
                            public void onStartConnect() {
                                showProgressBar(true);
                                bleD.setConnectState("连接中…");

                                bleItemProvider.notifyDataChanged();
                            }

                            @Override
                            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                                showProgressBar(false);
                                toast("连接失败");
                                bleD.setConnectState("连接失败");

                                bleItemProvider.notifyDataChanged();
                            }

                            @Override
                            public void onConnectSuccess(BleDevice bleDevice, BlePeripheralDevice gatt, int status) {
                                showProgressBar(false);
                                bleDevice.setConnectState("已连接");
                                toast("已连接");
                                bleItemProvider.notifyDataChanged();
                            }

                            @Override
                            public void onDisConnected(
                                    boolean isActiveDisConnected,
                                    BleDevice device,
                                    BlePeripheralDevice gatt,
                                    int status) {
                                bleD.setConnectState("连接断开");

                                bleItemProvider.notifyDataChanged();

                                if (isActiveDisConnected) {
                                    toast("断开了");
                                } else {
                                    toast("连接断开了");
                                    ObserverManager.getInstance().notifyObserver(bleD);
                                }
                            }
                        });
    }

    private void readRssi(BleDevice bleDevice) {
        BleManager.getInstance()
                .readRssi(
                        bleDevice,
                        new BleRssiCallback() {
                            @Override
                            public void onRssiFailure(BleException exception) {}

                            @Override
                            public void onRssiSuccess(int rssi) {}
                        });
    }

    private void setMtu(BleDevice bleDevice, int mtu) {
        BleManager.getInstance()
                .setMtu(
                        bleDevice,
                        mtu,
                        new BleMtuChangedCallback() {
                            @Override
                            public void onSetMTUFailure(BleException exception) {}

                            @Override
                            public void onMtuChanged(int mtu) {}
                        });
    }

    private void showProgressBar(boolean is) {
        if (is) {
            progressBar.setVisibility(Component.VISIBLE);
        } else {
            progressBar.setVisibility(Component.HIDE);
        }
    }

    private void toast(String msg) {
        new ToastDialog(getContext()).setContentText(msg).setDuration(2000).show();
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    protected void onStop() {
        super.onStop();
          mHandler.removeAllEvent();
        // 如果使用了普通蓝牙扫描，需要加上这行
        BleManager.getInstance().unSubscribeBluetooth();
    }
}
